; №22 4г - вказівники
; Починаємо в верхній лівій клітинці, а далі можемо рухатись лише в напрямку вказаному стрілкою.
; Де зупинитись - вибираємо самі. треба прийти в нижню праву клітинку. 

; Напрямки: 
; 7 8 9 
; 4   6
; 1 2 3

; поле:
(defconstant FIELD_SIZE 5)
(defconstant FIELD_SIZE-1 4)
(defconstant CELL_COUNT 25)

(setf field #2A((2 2 1 4 1) 
		(6 3 3 3 1) 
		(2 8 8 4 1) 
		(9 9 7 1 8) 
		(6 9 4 8 0)))

(defun nl () "newline"
	(format t "~%"))

(defun printfield (&optional (what field)) ; print field (by default) or any other 2d array
	(dotimes (y FIELD_SIZE) 
		(progn 
		(dotimes (x FIELD_SIZE)
			(format t "~2d " (aref what y x))
		)
		(nl))))

(setf visits (make-array (list FIELD_SIZE FIELD_SIZE) :initial-element 0))

(defun infield (x y) (and (>= x 0) (>= y 0) (< x FIELD_SIZE) (< y FIELD_SIZE)))

(defun waylist (x y dir)
	(if (not (infield x y))
		nil
		(cond ((= dir 1) 
			(cons (list x y) (waylist (- x 1) (+ y 1) dir)))
		((= dir 2) 
			(cons (list x y) (waylist x (+ y 1) dir)))
		((= dir 3) 
			(cons (list x y) (waylist (+ x 1) (+ y 1) dir)))
		((= dir 4) 
			(cons (list x y) (waylist (- x 1) y dir)))
		((= dir 6) 
			(cons (list x y) (waylist (+ x 1) y dir)))
		((= dir 7) 
			(cons (list x y) (waylist (- x 1) (- y 1) dir)))
		((= dir 8) 
			(cons (list x y) (waylist x (- y 1) dir)))
		((= dir 9) 
			(cons (list x y) (waylist (+ x 1) (- y 1) dir)))
		((= dir 0) nil)
		)))

(defun canvisit (x y)
	(and (infield x y) (= (aref visits y x) 0))
)
(defun visit (x y n) ; return true if going to cell x y in n-th route will lead you to finish
	(defun vis (x y) (setf (aref visits y x) n))
	(defun unvis (x y) (setf (aref visits y x) 0))
	(if (canvisit x y) 
		(progn 
		(if (and (= x 2) (= y 3) (not (= n 17))) (return-from visit nil)) ; special condition
		(vis x y)
		(if (and (= x FIELD_SIZE-1) (= y FIELD_SIZE-1) (= n CELL_COUNT)) 
			T
			(progn
			(dolist (point (cdr (waylist x y (aref field y x))))
				(if (visit (first point) (second point) (1+ n)) 
					(return-from visit T)))
			(unvis x y)	
			nil
			)))
		nil)
)

(printfield)
(print "Wait for it!")
(print (visit 0 0 1)) (nl)
(printfield visits)

(setf res 0)
(dotimes (x FIELD_SIZE) (setf res (+ res (aref visits x 2))))
(print res)
(print (reduce #'+ (mapcar (lambda (x) (aref visits x 2)) '(0 1 2 3 4))))
